#include "Base.h"

static int callback_on_event(int but_num);
/*总状态机*/
enum device_state_i{
    DEVICE_STATE_INIT = 1,
    DEVICE_STATE_RUNNING,
    // DEVICE_STATE_STOP, 
};

/*按钮状态机*/
enum button_state_i{
    BUTTON_STATE_NORMAL = 1,
    BUTTON_STATE_PRESS,
};
/*声明结构体*/
struct bl_button bl_buttons;
struct oled_show oled_shows;
static TaskHandle_t show_task;

typedef int (*machine_state_on_event_fn_t)(int but_num);
struct manchine_state_i
{
    enum device_state_i  device_state;
    enum button_state_i  button_state;
    machine_state_on_event_fn_t on_event;
    int button_num;
};

/*初始化设备*/
int device_state_init(struct manchine_state_i *self)
{
    bl_button_init(&bl_buttons);           // 初始化
    self->button_num = 0;
    self->device_state = DEVICE_STATE_RUNNING;  // 设备初始完毕,进入运行状态
    self->button_state = BUTTON_STATE_NORMAL;  // 按钮初始完毕,进入正常状态
    return 0;
}

/*按钮正常状态*/
int button_state_normal(struct manchine_state_i *self)
{
    self->button_num = bl_button_get_num(&bl_buttons);
    if (self->button_num)
    {
        self->button_state = BUTTON_STATE_PRESS;
    }else{
        self->button_num = 0;
    }
    return 0;
}

/*按钮按下状态*/
int button_state_press(struct manchine_state_i *self)
{
    self->on_event(self->button_num);
    if (!bl_button_get_num(&bl_buttons))
    {
        self->button_state = BUTTON_STATE_NORMAL;
    }
    return 0;
}

/*设备运行状态*/
int device_state_running(struct manchine_state_i *self)
{
    switch (self->button_state)
    {
    case BUTTON_STATE_NORMAL:
        return button_state_normal(self);
    case BUTTON_STATE_PRESS:
        return button_state_press(self);
    }
    return 0;
}

/*初始化状态机*/
int manchine_state_init(struct manchine_state_i *self,machine_state_on_event_fn_t on_event)
{
    self->on_event = on_event;
    self->device_state = DEVICE_STATE_INIT;      // 设备初始化
    return 0;
}

/*运行状态机*/
int machine_state_step(struct manchine_state_i *self)
{
    switch (self->device_state)
    {
    case DEVICE_STATE_INIT:
        return device_state_init(self);
    case DEVICE_STATE_RUNNING:
        return device_state_running(self);
    }
    return 0;
}


void Task_show(void *arg) 
{
    uint32_t ulNotifiedValue;
    const TickType_t xMaxBlockTime = pdMS_TO_TICKS( 50 );
    oled_show_init(&oled_shows);
    while (1)
    {
        xTaskNotifyWait(pdFALSE, ULONG_MAX, &ulNotifiedValue, xMaxBlockTime);
        if( ( ulNotifiedValue & _show1 ) != 0 )
        {
            /* Bit 0 was set - process whichever event is represented by bit 0. */
            printf("Bit 0 was set - process event 0.\n");
            oled_show_isr(&oled_shows);
            oled_show_up(&oled_shows);
            oled_show_start(&oled_shows,(show_content_fn_t)show_content);
        }
        if( ( ulNotifiedValue & _show2 )!= 0 )
        {
            /* Bit 1 was set - process whichever event is represented by bit 1. */
            printf("Bit 1 was set - process event 1.\n");
            oled_show_isr(&oled_shows);
            oled_show_down(&oled_shows);
            oled_show_start(&oled_shows,(show_content_fn_t)show_content);
        }
        if( ( ulNotifiedValue & _show3 )!= 0 )
        {
            /* Bit 2 was set - process whichever event is represented by bit 2. */
            oled_show_start(&oled_shows,(show_content_fn_t)show_content);
            printf("Bit 2 was set - process event 2.\n");
        }
        vTaskDelay(10 / portTICK_PERIOD_MS);
    }
}


void app_main()
{
    struct manchine_state_i fsm;
    manchine_state_init(&fsm,callback_on_event);
    xTaskCreate(Task_show, "task2", 4096, NULL, 20, &show_task);
    while (1)
    {
        machine_state_step(&fsm);
    }
}

/*在此处添加逻辑*/
static int callback_on_event(int but_num)
{
    switch (but_num)
    {
    case BUTTON_UP:
        printf("on_event1\n");
        xTaskNotify(show_task, _show1, eSetBits);
        break;
    case BUTTON_DOWN:
        printf("on_event2\n");
        xTaskNotify(show_task, _show2, eSetBits);
        break;
    case BUTTON_PRESS:
        printf("on_event3\n");
        xTaskNotify(show_task, _show3, eSetBits);
        break;    
    }
    return 0;
}